(ns client
    (:import [java.io InputStream OutputStream BufferedReader InputStreamReader PrintWriter]
			 [java.net Socket InetAddress]
			 [java.util Scanner]
			 [javax.swing JFrame JTextArea JTextField JScrollPane JButton JOptionPane]
			 [java.awt.event ActionEvent ActionListener WindowAdapter]
			 [java.awt Robot])
	(:gen-class))

(def serverIP (JOptionPane/showInputDialog "Input Server IP"))
(def serverPort (JOptionPane/showInputDialog "Input Server Port"))
(def selfIP (str (. (InetAddress/getLocalHost) getHostAddress)))
(def jf (JFrame. (str selfIP " - Client")))
(def msg_text (JTextArea.))
(def msg_scrl (JScrollPane. msg_text))
(def send_text (JTextArea.))
(def send_scrl (JScrollPane. send_text))
(def bt_send (JButton. "Send"))
(def bt_clear (JButton. "Clear"))
(def sock nil)
(def rbt (Robot.))

(defn send-text [text sock reader writer]
	(.println writer text)
	(.flush writer)
	(.setText send_text "")
	(if (= text "quit")
		(do
			(JOptionPane/showMessageDialog nil "The Socket Has Closed")
			(.close reader)
			(.close writer)
			(.close sock)
			(System/exit 0))))

(defn recive-text [sock reader writer]
	(loop []
		(.delay rbt 1000)
		(loop []
			(let [msg (. reader readLine)]
				(if msg
					(do
						(if (and (>= (.length msg) 22) (= (subs msg 0 22) "Admin Close The Socket"))
							(do
								(JOptionPane/showMessageDialog nil "Admin Close The Socket")
								(System/exit 0)))
						(.append msg_text (str msg \newline))
						(recur)))))
		(recur)))

(defn main []
	(doto jf
		(.setResizable false)
		(.setSize 400 650)
		(.setLocationRelativeTo nil)
		;(.setAlwaysOnTop true)
		(.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
		(.setLayout nil))

	(. msg_text setEditable false)

	(.setBounds msg_scrl 	  0   0 400 450)
	(.setBounds send_scrl 	  0 450 400 100)
	(.setBounds bt_send 	  0 550 200  50)
	(.setBounds bt_clear 	200 550 200  50)

	(doto jf
		(.add msg_scrl)
		(.add send_scrl)
		(.add bt_send)
		(.add bt_clear)
		(.setVisible true))
	
	(let [sock (Socket. serverIP (Integer/parseInt serverPort))]
		(let [writer (PrintWriter. (. sock getOutputStream))
			  reader (BufferedReader. (InputStreamReader. (. sock getInputStream)))]
			  (let [atn_send (proxy [ActionListener] [] (actionPerformed [e] (send-text (. send_text getText) sock reader writer)))
			  		atn_clear (proxy [ActionListener] [] (actionPerformed [e] (. msg_text setText "")))
			  		atn_close (proxy [WindowAdapter] [] (windowClosing [e] (send-text "quit" sock reader writer)))]
				(future (recive-text sock reader writer))
				(.addActionListener bt_send atn_send)
				(.addActionListener bt_clear atn_clear)
				(.addWindowListener jf atn_close)))))

(main)